using System;
using System.Collections.Generic;
using System.Xml;
using SSP.Api.Interfaces;

namespace SSP.Api
{
    /// <summary>
    /// 
    /// </summary>
    public class EXIF : IDeserializer
    {
        /// <summary>
        /// The aperture setting when the image was captured. 
        /// </summary>
        public string Aperture { get; set; }


        /// <summary>
        /// Gets or sets the comment.
        /// </summary>
        /// <value>The comment.</value>
        public string Comment { get; set; }

        /// <summary>
        /// The len's exposure when the image was captured.
        /// </summary>
        public string Exposure { get; set; }

        /// <summary>
        /// The exposure bias (if any). 
        /// </summary>
        public string ExposureBias { get; set; }

        /// <summary>
        /// Example: Tv-priority. 
        /// </summary>
        public string ExposureMode { get; set; }

        /// <summary>
        ///     Full string describing the flash status when the image was taken. Example: Red Eye, Compulsory Flash 
        /// </summary>
        public string Flash { get; set; }

        /// <summary>
        /// Whether the flash fired (true) or not (false). 
        /// </summary>
        public string FlashSimple { get; set; }

        /// <summary>
        ///  Example: 5.5 
        /// </summary>
        public decimal FocalLength { get; set; }

        /// <summary>
        ///  Example: 400 
        /// </summary>
        public int Iso { get; set; }

        /// <summary>
        ///     The manufacturer of the camera. Example: Canon 
        /// </summary>
        public string Make { get; set; }

        /// <summary>
        ///     The model of the camera. Example: Canon Digital Rebel 
        /// </summary>
        public string Model { get; set; }

        /// <summary>
        ///     Example: Center Weighted Average 
        /// </summary>
        public string MeteringMode { get; set; }

        /// <summary>
        /// Gets or sets the title.
        /// </summary>
        /// <value>The title.</value>
        public string Title { get; set; }

        /// <summary>
        ///     Examples: Auto, Sunny, Tungsten
        /// </summary>
        public string WhiteBalance { get; set; }

        /// <summary>
        /// Deserializes from an XmlReader and sets the object's properties.
        /// </summary>
        /// <param name="reader">The reader.</param>
        public void DeserializeFromReader(XmlReader reader)
        {
            // Start to use the reader.
            reader.Read();

            // Read all elements
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                switch (reader.Name)
                {
                    case "aperture":
                        Aperture = reader.ReadElementContentAsString();
                        break;
                    case "comment":
                        Comment = reader.ReadElementContentAsString();
                        break;
                    case "exposure":
                        Exposure = reader.ReadElementContentAsString();
                        break;
                    case "exposure_mode":
                        ExposureMode = reader.ReadElementContentAsString();
                        break;
                    case "exposure_bias":
                        ExposureBias = reader.ReadElementContentAsString();
                        break;
                    case "flash":
                        Flash = reader.ReadElementContentAsString();
                        break;
                    case "flash_simple":
                        FlashSimple = reader.ReadElementContentAsString();
                        break;
                    case "focal_length":
                        FocalLength = convertToDecimal(reader.ReadElementContentAsString());
                        break;
                    case "iso":
                        Iso = convertToInt(reader.ReadElementContentAsString());
                        break;
                    case "make":
                        Make = reader.ReadElementContentAsString();
                        break;
                    case "model":
                        Model = reader.ReadElementContentAsString();
                        break;
                    case "metering_mode":
                        MeteringMode = reader.ReadElementContentAsString();
                        break;
                    case "title":
                        Title = reader.ReadElementContentAsString();
                        break;
                    case "white_balance":
                        WhiteBalance = reader.ReadElementContentAsString();
                        break;
                    default:
                        System.Diagnostics.Trace.WriteLine("Unhandled xml element name '" + reader.Name + "'.");
                        _sDict[reader.Name] = reader.ReadElementContentAsString();
                        break;
                }
                reader.MoveToContent();
            }

            // Extremely important to read the node to its end.
            // next call of the reader methods will crash if not called.
            reader.ReadEndElement();
            //throw new System.NotImplementedException();
        }

        /// <summary>
        /// Converts to int.
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <returns></returns>
        private static int convertToInt(string str)
        {
            double ret;
            return Convert.ToInt32(double.TryParse(str, out ret) ? ret : 0);
        }

        private static decimal convertToDecimal(string str)
        {
            decimal retVal;
            decimal.TryParse(str, out retVal);
            return retVal;
        }

        /// <summary>
        /// Gets or sets the <see cref="System.String"/> with the specified property name.
        /// </summary>
        /// <value></value>
        public string this[string propertyName]
        {
            get { return _sDict[propertyName]; }
            set { _sDict[propertyName] = value; }
        }

        private readonly Dictionary<string, string> _sDict = new Dictionary<string, string>();
    }
}